[contents] [prev] [next] [top] [bottom] (2 out of 5)

What Happens In a Guard Construct

If no exceptions are reported during execution of the guarded code, the point of execution leaves the guarded code, executes the on exit code, and leaves the guard construct.

If an exception is reported during execution of the guarded code, the system stops executing the guarded code, executes the on exit code, then looks for all clauses in the catch list that catch the reported exception. For each clause in the catch list that catches the reported exception, the specified consequence occurs.

If any expression in the catching part of the guard construct uses the caught keyword, ScriptX immediately exits from the guard construct. None of the remaining statements in the current catch list or any surrounding catch lists are executed.

After ScriptX has checked the clauses in the current catch list, it reports (throws) the exception again, which means it checks for catch lists in any surrounding guard construct.

If any clause that catches the exception uses the throw again construct, the system throws the exception again immediately. In this case, it does not check the remaining statements in the catch list of the current guard construct, but immediately moves on to the surrounding one.

The system continues throwing the exception until the exception is explicitly caught by the caught construct. If the exception is not caught, if the caught construct is not specified for that exception, then the thread that was running when the exception occurred dies. If the exception occurs in the main thread, the title quits. Imagine the exception bouncing around from catcher to catcher until either something finally catches it for good, or it falls to the ground uncaught.

Specifying Exceptions to Catch

The guard construct, through the catching list, can catch individual exceptions, instances of a class of exceptions, or all exceptions.

To catch a particular exception, specify the Exception instance in the catch list. For example, this line catches only the divideByZero exception:

catching
	divideByZero : print "Divide by zero error. \n" 

To catch all instances of a class of exception, specify the exception class in the catching list. For example, this line catches all reported math exceptions, including divideByZero, lossOfRange, invalidNumber, and any other exceptions that are instances of the class MathException.

catching
	MathException : print "Some kind of math error." 

To catch all exceptions, specify the all keyword in the catch list. For example, this line catches all reported exceptions, including both system-defined exceptions and user-defined exceptions.

catching
	all : print "Look out, there's an error about." 

An Example: Printing Messages

The best way to demonstrate the use of exceptions is by example. This example prints a message about each kind of exception that was caught. This is an overly simple example, and you would normally want to print out more information about the precise conditions under which the exception occurred. Details on how to retrieve and print information about an exception are given in "Retrieving Information about the Exception" on page 180.

In the example, note the use of all: caught undefined as the last clause in the catch list. This clause explicitly catches every exception to prevent it from being thrown again, thus ensuring that the point of execution leaves the guard construct and continues executing the remainder of the code. By putting this line at the end of the catch list, you ensure that all other consequences of an exception occur before the exception is explicitly caught. The caught construct must return a value, which in this case is undefined.

During the execution of the guarded expressions, several kinds of exceptions could occur. First, the width or length might not be defined on box1. Secondly, the values of those instance variables might be undefined or some other non-numeric value. Finally, the length of the box might actually be 0.

Note that none of the catchers in the catch list has caught the exception yet. If any kind of exception occurs, the exception is finally caught by the fourth clause in the catch list (all). Since the exception has been caught, no more catchers in the catch list, or in any catch lists of surrounding guard expressions, are executed. The value of the guard expression is undefined. Since the expression was finally caught, execution continues after the outermost guard expression.

Nesting Guard Constructs

Expressions to be guarded within a guard expression can consist of or include other guard expressions. The use of multiple guard levels enables you to tune your exception-catching code. For example, you can write code that checks all expressions in a block for exceptions of type e1, additionally checks a subset of the expressions for exceptions of type e2, and checks a further subset for exceptions of type e3.

Usually, when an exception is reported by a guarded expressions in a guard construct, ScriptX checks each of the clauses in the catch list to find which ones catch the exception. Each exception in the catch list is checked, even if one has already caught the exception (unless one of the expressions uses the caught or throw again construct as discussed in "How to Control Throwing and Catching" on page 178.)

After checking all the clauses in the current catch list, ScriptX checks the catch list in the surrounding guard construct. This act of moving up to the surrounding guard construct to check for statements that catch an exception is known as throwing the exception. The system continues stepping up through the guard levels until one of the following occurs:

The following example demonstrates how nested guard expressions work.

S1 and S2 represent ScriptX expressions that can be guarded. The symbols e1, e2, e3, e4, and e5 represent lexical names, either instances of Exception or exception classes. In this example, expression S1 is guarded against exceptions e4 and e5, while expression S2 is guarded against exceptions e1, e2, e3, e4, and e5.

Consider what happens if S1 reports an exception:

  1. The point of execution jumps to the catch list in the outer guard expression and checks if the reported exception is an instance of e4. If so, it executes the expression repair D and continues with the next catcher in the list.
  2. The system checks if the exception is an instance of e5. If so, it executes the expression repair E and continues with the next catcher in the list, which is an all clause.
  3. The clause all: caught undefined explicitly catches the exception and prevents it from being thrown again.
  4. The system exits the outermost guard expression and executes the expression S3.
Consider what happens if S2 reports an exception:

  1. The system checks if the exception is an instance of e1. If so, it executes the expression repair A and continues with the next catcher in the list.
  2. The system checks if the exception is an instance of e2. If so, it executes the expression repair B and continues with the next catcher in the list.
  3. The system checks if the exception is an instance of e3. If so, it executes the expression repair C and continues with the next catcher in the list.
  4. On reaching the final catcher in the catch list, the system throws the exception again, which means it checks the catch list in the surrounding guard expression if there is one, which there is.
  5. The point of execution jumps to the catch list in the outer guard expression and checks if the reported exception is an instance of e4. If so, it executes the expression repair D and continues with the next catcher in the list.
  6. The system checks if the exception is an instance of e5. If so, it executes the expression repair E and continues with the next catcher in the list, which is an all clause.
  7. The catcher all: caught undefined explicitly catches the exception and prevents it from being thrown again.
  8. The system exits the outermost guard expression and executes the expression S3.
In several examples outlined in this chapter, the exception is finally caught by the all clause. This clause is really just a macro that expands to Exception-it is a shorthand way of intercepting all instances of Exception. Note that there is no particular reason, although the examples in this chapter show it, that the all clause has to be last in the catch list. A catch list can have no all clause, or it can have several.


This document is part of the ScriptX Language Guide, one of the volumes of the ScriptX Technical Reference Series. ScriptX is developed by the ScriptX Engineering Team at Apple Computer, successor to the Kaleida Engineering Team at Kaleida Labs, Inc.

Copyright 1996 Apple Computer, Inc. All Rights Reserved.